#ifndef LOG_MESSAGE_BLOCK_H
#define LOG_MESSAGE_BLOCK_H
#include <boost/array.hpp>
#include <string.h>
#include <stdexcept>
#include "../log_config.h"
namespace vpm
{
	namespace log 
	{
		namespace detail 
		{

			class MessageFullException  
			{
			public:
				MessageFullException(int wt):written(wt) 
				{

				}
				int written; 
			};

			class LogMessageBlockAccess;

			//the class is used for a wrapper for raw data buffer, but when using ostream or snprintf, 
			// they all need to operator on raw buffer, so , it seems a bad idea for wrapper it. 
			//every message has a flag indicate where the message should flow to ,like the console, file,etc. 
			class LogMessageBlock
			{

				enum 
				{
					LOG_MSG_BLOCK_SIZE = 4100,
				};
				typedef boost::array<char,LOG_MSG_BLOCK_SIZE+1> LogBufferType;

			public:		

				LogMessageBlock(int loggerType =LogConfig::LOGGER_NULL ):m_curPos(0),m_loggerType(loggerType)
				{
					m_logBuf[LOG_MSG_BLOCK_SIZE] =0;
				}

                //error in this function 
				inline void write(char ch) 
				{
					if (m_curPos >= LOG_MSG_BLOCK_SIZE)
					{
						//append myself to the message dispatcher 
						throw MessageFullException(0);
					}
					m_logBuf[m_curPos++] = ch; 		
				}

				void write(const char * pStr) 
				{		
					(*this) = pStr;
				}

				void append(const char * pStr)
				{
					(*this)+= pStr;
				}

				LogMessageBlock & operator = (const char * pStr)
				{
					m_curPos = 0;
					return (*this) += pStr;
				}

				LogMessageBlock & operator += (const char * pStr) //throw (MessageFullException)
				{
					const char * pTmp = pStr; 
					while(pTmp)
					{			
						if (m_curPos >= LOG_MSG_BLOCK_SIZE)
						{
							//append myself to the message dispatcher 
							throw MessageFullException(int(pTmp - pStr));
						}	
						m_logBuf[m_curPos++] = *pTmp++;
					}
					return *this; 
				}

				int logger_type()
				{
					return m_loggerType;
				}
				void logger_type(int loggerType)
				{
					m_loggerType = loggerType; 
				}
				inline int size()
				{
					return LOG_MSG_BLOCK_SIZE;
				}

				//c_array point, for sprintf 
				char * c_array()
				{
					return m_logBuf.begin();
				}

				//temp 
				const char * begin() const 
				{
					return m_logBuf.begin();
				}
				char * begin() 
				{
					return m_logBuf.begin();
				}

				const char * end() const 
				{		
					return (m_logBuf.data()+m_curPos );
				}
				char * end() 
				{
					return (m_logBuf.c_array()+m_curPos );
				}

				//it a bad interface. 
				void wt_ptr(int pos)
				{
					if (pos >=0)
					{
						m_curPos = pos > LOG_MSG_BLOCK_SIZE ? LOG_MSG_BLOCK_SIZE:pos; 
					}	
				}

				void clear_flag(int f)
				{
					m_loggerType = ~f & m_loggerType;
				}
				int length()
				{		
					return m_curPos;
				}

			private:
				friend class LogMessageBlockAccess;
				LogBufferType m_logBuf; 	
				int m_curPos; 
				int m_loggerType; 
			};

			class LogMessageBlockAccess
			{
			public:
				static LogMessageBlock::LogBufferType& get_buffer(LogMessageBlock & logMsg)
				{
					return logMsg.m_logBuf;
				}

			};
		}
	}
}
#endif // 
   
  
